package ru.mera.aaclog.parser;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @version 1.0 10/02/2013
 * @author anavdeev
 */
public class EchoClient {

    private static final String HOST_NAME = "localhost";
    private static final int TELNET_PORT = 15000;
    Socket telnetSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    private ArrayList<MessageParser> array;
    private StringBuffer str;

//    public EchoClient() throws IOException {
//        connect();
//    }

    private void connect() {
        try {
            // object of Socket
            telnetSocket = new Socket(HOST_NAME, TELNET_PORT);
            System.out.println("(1) Socket");

            // object of Output Stream  to write on socket
            out = new PrintWriter(telnetSocket.getOutputStream(), true);
            System.out.println("(2) PrintWriter");

            // Object of Buffered Reader to read command from terminal
            in = new BufferedReader(new InputStreamReader(telnetSocket.getInputStream()));
            System.out.println("(3) BufferedReader");
        } catch (IOException e) {
            Logger.getLogger(EchoClient.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    private void login() throws IOException {
        int c = 0;
        // read username prompt
        while (in.ready() && (c = in.read()) != -1) {
            System.out.print((char)c);
        }
        out.println("admin");
        out.flush();

        // read password prompt
        while (in.ready() && (c = in.read()) != -1) {
            System.out.print((char)c);
        }
        out.println("admin");
        out.flush();

        // read shell prompt
        while (in.ready() && (c = in.read()) != -1) {
            System.out.print((char)c);
        }
    }

    private void exec(String command) throws IOException {
        out.println(command);
        out.flush();
        int c;
        while (in.ready() && (c = in.read()) != -1) {
            System.out.print((char) c);
        }
    }

    private void execWait(String command) throws IOException {
        out.println(command);
        out.flush();
        int c;
        str = new StringBuffer();
        int offset = 0;
        array = new ArrayList<MessageParser>();
        while ((c = in.read()) != -1) {
//            System.out.print((char)c);
            str.append((char) c);

            int newOffset = 0;
            newOffset = str.indexOf(MessageParser.SIP_MESSAGE_TRACE_TAG, offset);
            if (newOffset != -1 && offset < newOffset) {
                if (offset > 0) {
                    MessageParser sipPackage = new MessageParser();
                    sipPackage.parse(str.substring(offset - 1, newOffset));
//                    System.out.println(sipPackage.getSipMessageType() + " * " + sipPackage.getcSeq() + " * " + sipPackage.getUserAgent());
                    array.add(sipPackage);
                }
                offset = newOffset + 1;
            }
        }
    }

    private void quit() throws IOException {
        out.println("quit");
        out.flush();
        int c;
        while (in.ready() && (c = in.read()) != -1) {
            System.out.print((char) c);
        }

        out.close();
        System.out.println("\n(7) out.close");
        in.close();
        System.out.println("(8) in.close");
        telnetSocket.close();
        System.out.println("(9) telnetSocket.close");
    }

    public void startSession() {
        try {
            this.connect();
            this.login();
            this.exec("cd trace");
            this.exec("act");
            this.exec("set sip 7");
//	    	DEBUG:root/trace/>help set
//	    	Sets trace controls identifying what debug information is to be captured.
//	    	Trace flags are bit-oriented, and multiple flags may be set by using the combined value.
//	    	syntax: set <control>, where <control> is one of:
//	    	        all <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	           Sets the trace flag for all available trace controls.
//	    	        io <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	           Sets the trace flag for all known IOChannel protocol types.
//	    	           Use "set io" to display all protocol types that will be affected.
//	    	        pmc <value>
//	    	           Values - 0 (Off), 1 (On), 2(Func/SM), 4(Error)
//	    	        ctxt <value>
//	    	           Values - 0 (Off), 1 (On), 2(Ctxt Q), 4(Error), 8(Ctxt)
//	    	        trans <value>
//	    	           Values - 0 (Off), 1 (On), 2 (With ASEData), 4 (Error)
//	    	        topology <value>
//	    	           Values - 0 (Off), 1 (Msg Seq), 2 (Verbose), 4 (Pre-Run), 8 (Post-Run)
//	    	        fact <value>
//	    	           Values - 0 (Off), 1 (On), 2(RT I/O), 4(Error), 8(Maint)
//	    	        db <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	        svc <value> [<all | <sid> <sid> ...>]
//	    	           Activation values - 0 (Off), 1 (On), 2(Verbose), 4(Error), 8(Process)
//	    	           <sid> indicates one or more service IDs to trace. Default is "all".
//	    	           Type "set svc" command to display all services that are enabled.
//	    	        uac <value>
//	    	           Values - 0 (Off), 1 (Client), 2(Users), 4(Error)
//	    	        cmiw <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	        imdb <value>
//	    	           Values - 0 (Off), 1 (Oper/Msg), 2(With Result), 4(With Traceback), 8 (Error)
//	    	        opidbg <value>
//	    	           Values - 0 (Off), 1 (Terse), 2 (Normal), 4 (Verbose)
//	    	        opi <value>
//	    	           Values - 0 (Off), 1 (Msgs)
//	    	        copi <value>
//	    	           Values - 0 (Off), 1 (Msgs)
//	    	        sopi <value>
//	    	           Values - 0 (Off), 1 (Msgs)
//	    	        parlayx <value>
//	    	           Values - 0 (Off), 1 (Msgs)
//	    	        sip <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	        bm <value>
//	    	           Values - 0 (Off), 1 (Msgs)
//	    	        subrprxyio <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	        cfiw <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
//	    	           Used to trace ConferenceUALSC channel messaging.
//	    	        iw <value>
//	    	           Values - 0 (Off), 1 (Msgs), 2(I/O Func/SM), 4(Error)
            this.exec("set svc 1 179");
//	    	Available services to use in "set svc" command :
//	    		   1 - IPTel (Root)
//	    		   5 - Locate User (Mod)
//	    		   7 - Authorize User (Mod)
//	    		   26 - Conf UA (Root)
//	    		   31 - Accounting (Mod)
//	    		   40 - Long Call Mod
//	    		   48 - Call Manager (Root)
//	    		   50 - Third Party CC (Mod)
//	    		   51 - Hold Retrieve (Mod)
//	    		   54 - Subscribe Base Processing (Mod)
//	    		   59 - Watcher Info (Mod)
//	    		   62 - Dialog Event (Mod)
//	    		   74 - Publish (Mod)
//	    		   76 - CallP Checkpointing (Mod)
//	    		   88 - Drop Call Leg Service (Mod)
//	    		   89 - Swap CM Service (Mod)
//	    		   92 - ClickToCall CM (Mod)
//	    		   105 - Interworking Call Model (Root)
//	    		   128 - Transport Security (Mod)
//	    		   149 - KPI (Mod)
//	    		   154 - Session Timer (Mod)
//	    		   155 - Session Timer Refresh (Mod)
//	    		   179 - Conf Event Subscription (Mod)
//	    		   180 - Conference SDP (Mod)
//	    		   181 - CCMP (Mod)
//	    		   182 - Media Server Routing (Mod)
//	    		   183 - SM Route (Mod)
//	    		   185 - Refer Conn
//	    		   186 - Bandwidth Management (Mod)
//	    		   187 - Conference Cascade (Mod)
//	    		   189 - Conference License (Mod)
//	    		   190 - Conference MGW (Root)
//	    		   195 - Reporting (Mod)
//	    		   197 - Conference Record
            this.exec("select *");
//	    	DEBUG:root/trace/>help select
//	    	Selects tags to enable when debug tracing is activated.
//	    	syntax: select * | <control>, where <control> is one of:
//	    	        user <name | name@host>
//	    	           Use any string which completes a startsWith match for the desired user to trace.
//	    	           E.g. "select user luke" "select user lukeduke" "select user lukeduke@hazzard.com"
//	    	        host <ip address>
//	    	           Use any string which completes a startsWith match for the desired ip address to trace.
//	    	           E.g. "select host 47.102" "select host 47.102.229.125"
//	    	        factory <protocol ID>
//	    	           Identify the protocol ID for the factory to enable tracing on.
//	    	           Use "select factory" to get a list of registered IO factorys.
//	    	           This must be used with the "set fact <value>" to identify the tracing level
//	    	           for IO factory tracing.
//	    	        imdb <all | <table name>>
//	    	           Identify the IMDB table to enable tracing on.
//	    	           Use "select imdb" to get a list of active tables.
//	    	           This must be used with the "set imdb <value>" to identify the tracing level
//	    	           for IMDB table tracing.
//	    	        ms <short name>
//	    	           Use any string which completes a startsWith match for the NE short name of the desired media server to trace.
//	    	           Enter "select ms" for a list of all configured media servers.
            this.exec("rep out sess ts on");
//	    	DEBUG:root/trace/>help rep
//	    	Reports on debug trace display / buffer status.
//	    	out - Used to identify the output for captured traces. Buffered, Debug session display, local file, or sent to log system.
//	    	For "file" output also specify file prefix, filesize (bytes), and number of files to rotate.
//	    	buff - Used to modify the per debug session buffer size.
//	    	ts - Used to indicate if timestamps are printed with each debug record displayed.
//	    	Reports current settings if no additional arguments provided.
//	    	syntax: rep [out <buff | sess | file [<prefix> <filesize> <numfiles>] | log> | buff <size> | ts <on | off>]
            this.execWait("start");

            this.quit();
        } catch (Exception e) {
            Logger.getLogger(EchoClient.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    ArrayList<MessageParser> getSize() {
        return array;
    }

}
